package com.example.jetpackcomposebasic

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.jetpackcomposebasic.todo.InputBar
import com.example.jetpackcomposebasic.todo.ToDoItem
import com.example.jetpackcomposebasic.todo.ToDoListBody
import com.example.jetpackcomposebasic.todo.viewmodel.impl.LiveDataViewModel
import com.example.jetpackcomposebasic.todo.viewmodel.impl.MutableListViewModel

class ToDoList : ComponentActivity() {
    /**
     * 毕竟Composable的主要职责是负责UI的显示。所以当Stateful的业务逻辑变得越发复杂时，
     * 可以将Stateful的状态提到ViewModel管理，Stateful也就变为了一个Stateless，
     * 通过参数传入不同ViewModel即可替换具体业务逻辑，可复用性和可测试性也大大提高。
     *
     * viewModel()是一个@Composable方法，用于在Composable中创建ViewModel。
     * CounterScreen通过viewModel()创建了一个CounterViewModel类型的ViewModel,
     * ViewModel持有状态counter。
     *
     * viewModel()会从当前最近的ViewModelStore中获取ViewModel实例，这个ViewModelStore可能是一个Activity，
     * 也可能是一个Fragment。如果ViewModel不存在，就创建一个新的并存入ViewModelStore。
     * 只要ViewModelStore不销毁，其内部的ViewModel将一直存活。
     * 例如一个Activity中的Composable通过viewModel()创建的ViewModel被当前的Activity持有。
     * 在Activity销毁之前，ViewModel将一直存在，viewModel()每次调用将返回同一个实例，所以此时可以不使用remember进行缓存。
     *
     *
     * */
    private val toListViewModel: MutableListViewModel by viewModels<MutableListViewModel>()

    val viewModelByLiveData: LiveDataViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ListBodyByViewModelFunction()
        }
    }

    /**
     * 1、对有状态组件进行状态上提来实现 解耦
     * 使得UI函数能被复用不同业务逻辑
     *
     * 简单的状态上提到最小父函数
     */
    @Composable
    private fun ListBodyByRememberDirectly() {

        val todos: MutableList<ToDoItem> = remember {
            mutableStateListOf()
        }
        ToDoListBody(todos, {
            todos.add(it)
        }, {
            todos.remove(it)
        })
    }

    /**
     * 2、基于 LiveData 实现 ViewModel
     *
     * 在MVVM架构中，View通过LiveData等观察ViewModel的状态，当LiveData的数据变化时，
     * 会以数据流的形式通知View，因此LiveData这类工具也被称为流式数据框架或响应式数据框架。
     * 同类框架还有RxJava、Flow等。
     * 在Compose中同样的功能由State负责完成，
     * 可以将上述这些流式数据转换为Composable的State，当LiveData等变化时，
     * 可以驱动Composable完成重组。
     *
     * 使用相应的扩展库就能把mvvm无缝迁移到jetpack compose中，
     * 比如借助 runtime-livedata 库就能在 LiveData 对象上调用 observeAsState()
     * 从而将其转为 State 对象
     */
    @Composable
    private fun ListBodyByLiveDataViewModel() {


        /*

        需要依赖库 来把 LiveData 对象转换为 State 对象


        需要引入才能使用 observeAsState() 函数
        runtime-livedata={group="androidx.compose.runtime",name="runtime-livedata"}
            * */
        val toDoList: List<ToDoItem> by viewModelByLiveData.toDoList.observeAsState(arrayListOf())

        ToDoListBody(toDoList, viewModelByLiveData::add, viewModelByLiveData::remove)


    }

    /**
     * 3、基于MutableState 实现ViewModel
     */
    @Composable
    fun ListBodyByMutableListViewModel() {
        ToDoListBody(
            toListViewModel.toDoList,
            toListViewModel::addToDo,
            toListViewModel::removeToDo
        )
    }

    /**
     * 注意 viewModel() 函数只能在 @Composable 函数中被调用
     * 需要引入 lifecycle-viewmodel-compose 依赖
      */
    @Composable
    fun ListBodyByViewModelFunction() {


        val viewModel: MutableListViewModel = viewModel()

        Column {
            InputBar(viewModel::addToDo)
            ToDoListBody(
                viewModel.toDoList,
                viewModel::addToDo,
                viewModel::removeToDo
            )
        }

    }
}


